#!/usr/bin/env bash

usage() {
  cat <<EOF
USAGE

  $0 [--help] [--debug] [--docker]

SUMMARY

  Compile the Tree-sitter WASM library. This will create two files in the
  \`lib/binding_web\` directory: \`tree-sitter.js\` and \`tree-sitter.wasm\`.

REQUIREMENTS

  You must have either the \`emcc\` command or the \`docker\` command
  on your PATH for this to work.

OPTIONS

  --help:   Display this message.
  --debug:  Compile the library more quickly, with fewer optimizations
            and more runtime assertions.
  --docker: Run emscripten using docker, even if \`emcc\` is installed.
            By default, \`emcc\` will be run directly when available.

EOF
}

set -e

web_dir=lib/binding_web
exports=$(cat ${web_dir}/exports.json)
emscripten_flags="-O3"
minify_js=1
force_docker=0

while [[ $# > 0 ]]; do
  case "$1" in
    --debug)
      minify_js=0
      emscripten_flags="-s ASSERTIONS=1 -s SAFE_HEAP=1 -O0"
      ;;

    --help)
      usage
      exit 0
      ;;

    --docker)
      force_docker=1
      ;;

    *)
      usage
      echo "Unrecognized argument '$1'"
      exit 1
      ;;
  esac
  shift
done

emcc=
if which emcc > /dev/null && [[ "$force_docker" == "0" ]]; then
  export EMCC_FORCE_STDLIBS=libc++
  emcc=emcc
elif which docker > /dev/null; then
  emcc="docker run               \
    --rm                         \
    -v $(pwd):/src:Z             \
    -u $(id -u)                  \
    -e EMCC_FORCE_STDLIBS=libc++ \
    trzeci/emscripten-slim       \
    emcc"
else
  echo 'You must have either `docker` or `emcc` on your PATH to run this script'
  exit 1
fi

mkdir -p target/scratch

# Use emscripten to generate `tree-sitter.js` and `tree-sitter.wasm`
# in the `target/scratch` directory
$emcc                                \
  -s WASM=1                          \
  -s TOTAL_MEMORY=33554432           \
  -s ALLOW_MEMORY_GROWTH=1           \
  -s MAIN_MODULE=2                   \
  -s NO_FILESYSTEM=1                 \
  -s "EXPORTED_FUNCTIONS=${exports}" \
  $emscripten_flags                  \
  -std=c99                           \
  -D 'fprintf(...)='                 \
  -I lib/src                         \
  -I lib/include                     \
  -I lib/utf8proc                    \
  --js-library ${web_dir}/imports.js \
  --pre-js ${web_dir}/prefix.js      \
  --post-js ${web_dir}/binding.js    \
  lib/src/lib.c                      \
  ${web_dir}/binding.c               \
  -o target/scratch/tree-sitter.js

# Use terser to write a minified version of `tree-sitter.js` into
# the `lib/binding_web` directory.
if [[ "$minify_js" == "1" ]]; then
  if [ ! -d ${web_dir}/node_modules/terser ]; then
    (
      cd ${web_dir}
      npm install
    )
  fi
  ${web_dir}/node_modules/.bin/terser   \
    --compress                       \
    --mangle                         \
    --keep-fnames                    \
    --keep-classnames                \
    -- target/scratch/tree-sitter.js \
    > $web_dir/tree-sitter.js
else
  cp target/scratch/tree-sitter.js $web_dir/tree-sitter.js
fi

mv target/scratch/tree-sitter.wasm $web_dir/tree-sitter.wasm
